package org.patterns.structural.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * 自定义动态代理请求处理程序，用于记录DAO操作日志及方法调用时间
 * 通过实现InvocationHandler接口实现代理方法增强功能
 */
public class DAOLogHandler implements InvocationHandler {
    private Calendar calendar;
    private Object object;

    /**
     * 默认构造器，用于创建基础处理器实例
     */
    public DAOLogHandler() {
    }

    /**
     * 构造器注入需要被代理的真实主题对象
     * @param object 被代理的目标对象实例，代理会将方法调用转发给该对象
     */
    public DAOLogHandler(Object object) {
        this.object = object;
    }

    /**
     * 实现invoke()方法，调用在真实主题类中定义的方法
     * 代理方法调用处理器，实现方法调用前后的日志增强逻辑
     *
     * @param proxy  动态生成的代理类实例
     * @param method 被调用的方法对象，反映代理实例上调用的接口方法
     * @param args   调用参数数组，原始类型参数会被包装为对应包装类对象
     * @return 被代理对象方法的调用结果
     * @throws Throwable 目标方法可能抛出的任何异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置日志记录：记录方法开始调用时间
        beforeInvoke();

        // 打印代理实例和方法信息
        System.out.println("代理对象：" + proxy.getClass().getName());
        System.out.println("调用方法：" + method.getName());

        // 通过反射调用被代理对象的原始方法
        Object result = method.invoke(object, args);

        // 后置日志记录：标记方法调用完成
        afterInvoke();
        return result;
    }

    /**
     * 记录方法调用开始时间信息
     * 使用GregorianCalendar获取精确到秒的时间信息并输出
     */
    public void beforeInvoke() {
        calendar = new GregorianCalendar();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        String time = hour + ":" + minute + ":" + second;
        System.out.println("调用时间：" + time);
    }

    /**
     * 记录方法调用结束的标记日志
     * 在方法正常执行完成后输出结束标识
     */
    public void afterInvoke() {
        System.out.println("方法调用结束！");
    }
}

